const { Readable } = require('stream');
const path = require('path');

function readBody(stream) {
  if (stream instanceof Readable) {
    return new Promise((resolve, reject) => {
      try {
        let result = '';

        stream.on('data', (chunk) => {
          result += chunk;
        })

        stream.on('end', () => {
          resolve(result)
        })
      } catch (error) {
        reject(error)
      }
    })
  } else {
    return stream;
  }
}

async function transformIndexHtml(
  html,
  transforms,
  apply,
  isBuild
) {
  const trans = transforms
    .map((t) => {
      return typeof t === 'function' && apply === 'post'
        ? t
        : t.apply === apply
          ? t.transform
          : undefined
    })
    .filter(Boolean)
  let code = html
  for (const transform of trans) {
    code = await transform({ isBuild, code })
  }
  return code
}

const injectReplaceRE = [/<head>/, /<!doctype html>/i]

function injectScriptToHtml(html, script) {
  // inject after head or doctype
  for (const re of injectReplaceRE) {
    if (re.test(html)) {
      return html.replace(re, `$&${script}`)
    }
  }
  // if no <head> tag or doctype is present, just prepend
  return script + html
}

function isEqualBlock(a, b) {
  if (!a && !b) return true
  if (!a || !b) return false
  // src imports will trigger their own updates
  if (a.src && b.src && a.src === b.src) return true
  if (a.content !== b.content) return false
  const keysA = Object.keys(a.attrs)
  const keysB = Object.keys(b.attrs)
  if (keysA.length !== keysB.length) {
    return false
  }
  return keysA.every((key) => a.attrs[key] === b.attrs[key])
}

function slash(path) {
  const isExtendedLengthPath = path.startsWith('\\\\?\\');

  if (isExtendedLengthPath) {
    return path;
  }

  return path.replace(/\\/g, '/');
}

function fileToRequest(filePath, root = process.cwd()) {
  return '/' + slash(path.relative(root, filePath)).replace(/^public\//, '')
}

function resolveRelativePath(from, to, root = process.cwd()) {
  let importToUrl = path.resolve(path.dirname(path.join(root, to)), from);
  return '/' + path.relative(root, importToUrl);
}

module.exports = {
  readBody,
  transformIndexHtml,
  injectScriptToHtml,
  isEqualBlock,
  fileToRequest,
  resolveRelativePath
}